package com.hivclassifier;

import java.util.Random;

import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.classifiers.bayes.BayesNet;
import weka.core.Instance;
import weka.core.converters.ConverterUtils.DataSource;

import com.hivclassifier.models.HivClassModel.CoreceptorEnums;

public class HivClassifierController {

	private static Ccr5FeaturesInstances trainingInstances;
	private static BayesNet bayes;

	public static void init() {
		try {
//			bayes = new BayesNet();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static Evaluation appendToTrainingSetAndEvaluate(String filePathOfTrainingFile) {
		Evaluation evaluationBayes = null;
		
		try {
			DataSource trainingDataSource;
			
			if (filePathOfTrainingFile != null && !filePathOfTrainingFile.equals("") ) {
				trainingDataSource = new DataSource(filePathOfTrainingFile);
				if (trainingInstances == null) {
					trainingInstances = new Ccr5FeaturesInstances(trainingDataSource.getDataSet());
				} else {
					trainingInstances.appendInstances(trainingDataSource.getDataSet(), true);
				}
			}
			
			bayes = new BayesNet();
			bayes.buildClassifier(trainingInstances);
			evaluationBayes = new Evaluation(trainingInstances);
			evaluationBayes.crossValidateModel(bayes, trainingInstances, 5, new Random());
			
//	        SMO smo = new SMO();
//	        smo.buildClassifier(trainingInstances);
//	        evaluationBayes = new Evaluation(trainingInstances);
//	        evaluationBayes.crossValidateModel(smo, trainingInstances, 5, new Random());
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
		return evaluationBayes;
	}
	
	public static String[][] performClassification(String filePathOfTestFile) {
		String[][] resultClassificationMatrix = null;

		try {
			DataSource testDataSource = null;
			
			if (filePathOfTestFile != null && !filePathOfTestFile.equals("") ) {
				testDataSource = new DataSource(filePathOfTestFile);
			}

			Ccr5FeaturesInstances testInstances = new Ccr5FeaturesInstances(testDataSource.getDataSet(), false);
			resultClassificationMatrix = new String[testInstances.numInstances()][2];

			Instance instance;
			int i;
			
			for (i = 0; i < testInstances.numInstances(); i++) {
				instance = testInstances.instance(i);
				try {
					resultClassificationMatrix[i][0] = instance.attribute(0).value(i);
				} catch (Exception e) {
					resultClassificationMatrix[i][0] = testInstances.instance(i).toString().split(",")[0];
				}
				try {
					resultClassificationMatrix[i][1] = doubleToStringClass(bayes.classifyInstance(instance));
				} catch (Exception e) {
					resultClassificationMatrix[i][1] = "N/A";
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		
		return resultClassificationMatrix;
	}
	
	private static String doubleToStringClass(double value) {
		if (value == 2.0) {
			return CoreceptorEnums.CCR5.name();
		} else if (value == 1.0) {
			return CoreceptorEnums.DUAL.name();
		} else if (value == 0.0) {
			return CoreceptorEnums.CXCR4.name();
		} else {
			return "Not classified";
		}
	}
	
	public static Classifier getBayesClassifier() {
		return bayes;
	}
	
	public static void setBayesClassifier(Classifier loadBayesClassifier) {
		bayes = (BayesNet) loadBayesClassifier;
		if (bayes == null) {
			trainingInstances = null;
		}
	}
}
